#ifndef DOMAIN
#define DOMAIN

#include <string>
#include <stdexcept>
#include <iostream>
#include <cstdlib>

using namespace std;

/** Classe basica que prove a estrutura para os tipos baseados em string. */
class StringObject {
        virtual void validate(string) throw (invalid_argument) = 0;
    protected:
       string value;
    public:
        string title;
        StringObject(){
            value = ' ';
            title = "a String";
        }
        virtual void set(const string&) throw (invalid_argument);
        virtual string get() const;
};

/** Classe basica que prove a estrutura para os tipos baseados em float. */
class FloatObject {
        virtual void validate(float) throw (invalid_argument) = 0;
    protected:
       float value;
    public:
        string title;
        FloatObject(){
            value = 0.0;
            title = "o Float";
        }
        virtual void set(const float&) throw (invalid_argument);
        virtual float get() const;
};

/** Classe basica que prove a estrutura para os tipos baseados em int. */
class IntObject {
        virtual void validate(int) throw (invalid_argument) = 0;
    protected:
       int value;
    public:
        string title;
        IntObject(){
            value = 0;
            title = "o Int";
        }
        virtual void set(const int&) throw (invalid_argument);
        virtual int get() const;
};

/** Classe derivada de StringObject para armazenar o nome do usuario. */
class Name : public StringObject {
        void validate(string) throw (invalid_argument);
    public:
        Name(){
            title = "o Nome";
        }
        Name(string) throw (invalid_argument);
        ~Name(){}
};

/** Classe derivada de StringObject para armazenar a senha do usuario. */
class Password : public StringObject {
        void validate(string) throw (invalid_argument);
    public:
        Password(){
            title = "a Senha";
        }
        Password(string) throw (invalid_argument);
        ~Password(){}
};

/** Classe derivada de StringObject para armazenar o endereco do usuario. */
class Address : public StringObject {
        void validate(string) throw (invalid_argument);
    public:
        Address(){
            title = "o Endereco";
        }
        Address(string) throw (invalid_argument);
        ~Address(){}
};

/** Classe derivada de StringObject para armazenar o CPF do usuario. */
class CPF : public StringObject {
        void validate(string) throw (invalid_argument);
    public:
        CPF(){
            title = "o CPF";
        }
        CPF(string) throw (invalid_argument);
        ~CPF(){}
};

/** Classe derivada de FloatObject para armazenar o valor total das vendas do usuario. */
class TotalSales : public FloatObject {
        //void validate(float) throw (invalid_argument);
    public:
        TotalSales(){
            title = "o Total de Vendas";
        }
        TotalSales(float) throw (invalid_argument);
        ~TotalSales(){}
};

/** Classe derivada de FloatObject para armazenar precos. */
class Price : public FloatObject {
        void validate(float) throw (invalid_argument);
    public:
        Price(){
            title = "o Preco";
        }
        Price(float) throw (invalid_argument);
        ~Price(){}
};

/** Classe derivada de StringObject para armazenar o identificador da foto. */
class Identifier : public StringObject {
        void validate(string) throw (invalid_argument);
    public:
        Identifier(){
            title = "o Identificador";
        }
        Identifier(string) throw (invalid_argument);
        ~Identifier(){}
};

/** Classe derivada de StringObject para armazenar a descricao da foto. */
class Description : public StringObject {
        void validate(string) throw (invalid_argument);
    public:
        Description(){
            title = "a Descricao";
        }
        Description(string) throw (invalid_argument);
        ~Description(){}
};

/** Classe derivada de IntObject para armazenar nivel de acesso para o album. */
class AccessLevel : public IntObject {
        void validate(int) throw (invalid_argument);
    public:
        AccessLevel(){
            title = "o Nivel de Acesso";
        }
        AccessLevel(int) throw (invalid_argument);
        ~AccessLevel(){}
};

/** Classe derivada de IntObject para armazenar a quantidade de albuns no pedido. */
class Quantity : public IntObject {
        void validate(int) throw (invalid_argument);
    public:
        Quantity(){
            title = "a Quantidade";
        }
        Quantity(int) throw (invalid_argument);
        ~Quantity(){}
};

/** Classe derivada de StringObject para armazenar a data da foto. */
class Date : public StringObject {
        void validate(string) throw (invalid_argument);
    public:
        Date(){
            title = "a Data";
        }
        Date(string) throw (invalid_argument);
        ~Date(){}
};

/** Classe derivada de IntObject para armazenar a velocidade do obturador. */
class Speed : public FloatObject {
        void validate(float) throw (invalid_argument);
    public:
        Speed(){
            title = "a Velocidade";
        }
        Speed(float) throw (invalid_argument);
        ~Speed(){}
};

/** Classe derivada de FloatObject para armazenar a abertura do diafragma. */
class Openness : public FloatObject {
        void validate(float) throw (invalid_argument);
    public:
        Openness(){
            title = "a Abertura";
        }
        Openness(float) throw (invalid_argument);
        ~Openness(){}
};

/** Classe derivada de IntObject para armazenar a ISO (sensibilidade do sensor de luz da camera). */
class ISO : public IntObject {
        void validate(int) throw (invalid_argument);
    public:
        ISO(){
            title = "a ISO";
        }
        ISO(int) throw (invalid_argument);
        ~ISO(){}
};

#endif
